package com.hzhr.iot.collect.protocol.util;

import com.hzhr.iot.collect.constant.MessageFieldKeyEnum;
import com.hzhr.iot.collect.constant.RequestResponseFlagEnum;
import com.hzhr.iot.collect.constant.TransferDirEnum;
import com.hzhr.iot.collect.constant.entity.*;
import com.hzhr.iot.collect.constant.entity.constant.*;
import com.hzhr.iot.collect.entity.CommandCountEntity;
import com.hzhr.iot.collect.service.CommandCountService;
import com.hzhr.iot.collect.service.helper.Device_IotDeviceServiceHelper;
import com.hzhr.iot.collect.service.helper.Device_IotDevice_CurrentMessageIdServiceHelper;
import com.hzhr.iot.collect.util.DateUtil;
import com.hzhr.iot.collect.util.StrUtil;
import com.hzhr.iot.core.util.HzhrTypeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
public class MessageUtil {
    @Autowired
    CommandCountService commandCountService;
    @Autowired
    Device_IotDeviceServiceHelper device_iotDeviceServiceHelper;
    @Autowired
    Device_IotDevice_CurrentMessageIdServiceHelper device_iotDevice_currentMessageIdServiceHelper;

    public Map<MessageFieldKeyEnum, Object> generateResponse(int protocolId, Map<MessageFieldKeyEnum, Object> reqMessageObj,
                         String responseCode) {
        Map<MessageFieldKeyEnum, Object> messageHeadObj = generateMessageHeadObj(protocolId, reqMessageObj);
        messageHeadObj.put(MessageFieldKeyEnum.REQ_RESP_FLAG, RequestResponseFlagEnum.RESP.getIdForMessage());
        Map<MessageFieldKeyEnum, Object> dataAreaObj = new HashMap<>();
        dataAreaObj.put(MessageFieldKeyEnum.RESPONSE_CODE, responseCode);
        Map<MessageFieldKeyEnum, Object> respMessageObj = generateMessageObj(protocolId, messageHeadObj, dataAreaObj);

        return respMessageObj;
    }

    public Map<MessageFieldKeyEnum, Object> generateDtuResponse(int protocolId, Map<MessageFieldKeyEnum, Object> reqMessageObj,
                                                             String responseCode, String dtuNo) {
        Map<MessageFieldKeyEnum, Object> messageHeadObj = generateMessageHeadObj(protocolId, reqMessageObj);
        messageHeadObj.put(MessageFieldKeyEnum.REQ_RESP_FLAG, RequestResponseFlagEnum.RESP.getIdForMessage());
        Map<MessageFieldKeyEnum, Object> dataAreaObj = new HashMap<>();
        dataAreaObj.put(MessageFieldKeyEnum.RESPONSE_CODE, responseCode);
        dataAreaObj.put(MessageFieldKeyEnum.RESP_IOT_DEVICE_ID, dtuNo);
        Map<MessageFieldKeyEnum, Object> respMessageObj = generateMessageObj(protocolId, messageHeadObj, dataAreaObj);

        return respMessageObj;
    }
    public Map<MessageFieldKeyEnum, Object> generateDtuResponse(int protocolId, Map<MessageFieldKeyEnum, Object> reqMessageObj,
                                                                String responseCode, String dtuNo, String slaveStationNo, String meterNo) {
        Map<MessageFieldKeyEnum, Object> messageHeadObj = generateMessageHeadObj(protocolId, reqMessageObj);
        messageHeadObj.put(MessageFieldKeyEnum.REQ_RESP_FLAG, RequestResponseFlagEnum.RESP.getIdForMessage());
        Map<MessageFieldKeyEnum, Object> dataAreaObj = new HashMap<>();
        dataAreaObj.put(MessageFieldKeyEnum.RESPONSE_CODE, responseCode);
        dataAreaObj.put(MessageFieldKeyEnum.RESP_IOT_DEVICE_ID, dtuNo);
        dataAreaObj.put(MessageFieldKeyEnum.RESP_SLAVE_STATION_ID, slaveStationNo);
        dataAreaObj.put(MessageFieldKeyEnum.RESP_COLLECT_DEVICE_ID, meterNo);
        Map<MessageFieldKeyEnum, Object> respMessageObj = generateMessageObj(protocolId, messageHeadObj, dataAreaObj);

        return respMessageObj;
    }
    public Map<MessageFieldKeyEnum, Object> generateDtuResponse(int protocolId, Map<MessageFieldKeyEnum, Object> reqMessageObj,
                                                                String responseCode, String dtuNo, Date date) {
        Map<MessageFieldKeyEnum, Object> messageHeadObj = generateMessageHeadObj(protocolId, reqMessageObj);
        messageHeadObj.put(MessageFieldKeyEnum.REQ_RESP_FLAG, RequestResponseFlagEnum.RESP.getIdForMessage());
        Map<MessageFieldKeyEnum, Object> dataAreaObj = new HashMap<>();
        dataAreaObj.put(MessageFieldKeyEnum.RESPONSE_CODE, responseCode);
        dataAreaObj.put(MessageFieldKeyEnum.RESP_IOT_DEVICE_ID, dtuNo);
        dataAreaObj.put(MessageFieldKeyEnum.RESP_CURRENT_DATE, DateUtil.dateToStr(date, "yyyyMMdd"));
        dataAreaObj.put(MessageFieldKeyEnum.RESP_CURRENT_TIME, DateUtil.dateToStr(date, "HHmmss"));
        Map<MessageFieldKeyEnum, Object> respMessageObj = generateMessageObj(protocolId, messageHeadObj, dataAreaObj);

        return respMessageObj;
    }
    public Map<MessageFieldKeyEnum, Object> generateCcrResponse(int protocolId, Map<MessageFieldKeyEnum, Object> reqMessageObj, String responseCode, String ccrNo) {
        Map<MessageFieldKeyEnum, Object> messageHeadObj = generateMessageHeadObj(protocolId, reqMessageObj);
        messageHeadObj.put(MessageFieldKeyEnum.REQ_RESP_FLAG, Integer.valueOf(RequestResponseFlagEnum.RESP.getIdForMessage()));
        Map<MessageFieldKeyEnum, Object> dataAreaObj = new HashMap<MessageFieldKeyEnum, Object>();
        dataAreaObj.put(MessageFieldKeyEnum.RESPONSE_CODE, responseCode);
        dataAreaObj.put(MessageFieldKeyEnum.RESP_CONCENTRATOR_NO, ccrNo);
        return generateMessageObj(protocolId, messageHeadObj, dataAreaObj);
    }

    public Map<MessageFieldKeyEnum, Object> generatePressureMonitorResponse(int protocolId, Map<MessageFieldKeyEnum, Object> reqMessageObj,
                                                                String responseCode, Map<MessageFieldKeyEnum, Object> content) {
        Map<MessageFieldKeyEnum, Object> messageHeadObj = new HashMap<>();
        messageHeadObj.put(MessageFieldKeyEnum.FUNCTION_CODE, reqMessageObj.get(MessageFieldKeyEnum.FUNCTION_CODE));
        messageHeadObj.put(MessageFieldKeyEnum.IOT_DEVICE_ID, reqMessageObj.get(MessageFieldKeyEnum.IOT_DEVICE_ID));
        messageHeadObj.put(MessageFieldKeyEnum.MESSAGE_ID, reqMessageObj.get(MessageFieldKeyEnum.MESSAGE_ID));
        messageHeadObj.put(MessageFieldKeyEnum.CONTROL_CODE, "176");

        Map<MessageFieldKeyEnum, Object> dataAreaObj = new HashMap<>();
        dataAreaObj.put(MessageFieldKeyEnum.RESPONSE_CODE, responseCode);
        if (content != null) {
            dataAreaObj.putAll(content);
        }
        Map<MessageFieldKeyEnum, Object> respMessageObj = generateMessageObj(protocolId, messageHeadObj, dataAreaObj);

        return respMessageObj;
    }
    public Map<MessageFieldKeyEnum, Object> generatePressureMonitorReq(int protocolId, String functionCode, String iotDeviceId,
                                                                            String messageId, Map<MessageFieldKeyEnum, Object> content) {
        Map<MessageFieldKeyEnum, Object> messageHeadObj = new HashMap<>();
        messageHeadObj.put(MessageFieldKeyEnum.FUNCTION_CODE, functionCode);
        messageHeadObj.put(MessageFieldKeyEnum.IOT_DEVICE_ID, iotDeviceId);
        messageHeadObj.put(MessageFieldKeyEnum.MESSAGE_ID, messageId);
        messageHeadObj.put(MessageFieldKeyEnum.CONTROL_CODE, "56");

        Map<MessageFieldKeyEnum, Object> dataAreaObj = new HashMap<>();
        if (content != null) {
            dataAreaObj.putAll(content);
        }
        Map<MessageFieldKeyEnum, Object> respMessageObj = generateMessageObj(protocolId, messageHeadObj, dataAreaObj);

        return respMessageObj;
    }

    public Map<MessageFieldKeyEnum, Object> generateMessageHeadObj(int protocolId, Map<MessageFieldKeyEnum, Object> messageObj) {
        Map<MessageFieldKeyEnum, Object> messageHeadObj = new HashMap<>();
        messageHeadObj.put(MessageFieldKeyEnum.MESSAGE_SIZE, messageObj.get(MessageFieldKeyEnum.MESSAGE_SIZE));
        messageHeadObj.put(MessageFieldKeyEnum.FUNCTION_CODE, messageObj.get(MessageFieldKeyEnum.FUNCTION_CODE));
        messageHeadObj.put(MessageFieldKeyEnum.TRANSFER_DIR, messageObj.get(MessageFieldKeyEnum.TRANSFER_DIR));
        messageHeadObj.put(MessageFieldKeyEnum.REQ_RESP_FLAG, messageObj.get(MessageFieldKeyEnum.REQ_RESP_FLAG));
        messageHeadObj.put(MessageFieldKeyEnum.IOT_DEVICE_ID, messageObj.get(MessageFieldKeyEnum.IOT_DEVICE_ID));
        messageHeadObj.put(MessageFieldKeyEnum.MESSAGE_ID, messageObj.get(MessageFieldKeyEnum.MESSAGE_ID));

        return messageHeadObj;
    }

    public Map<MessageFieldKeyEnum, Object> generateMessageObj(int protocolId, Map<MessageFieldKeyEnum, Object> messageHead,
                                                               Map<MessageFieldKeyEnum, Object> dataArea) {
        MessagetmpEntity messagetmp = MessagetmpEntityConstant.getMessagetmpEntityByProtocolId(protocolId);

        String functionCode = messageHead.get(MessageFieldKeyEnum.FUNCTION_CODE).toString();
        String reqRespFlagStr = HzhrTypeUtil.object2string(messageHead.get(MessageFieldKeyEnum.REQ_RESP_FLAG));
        Integer requestResponseFlagIdForMessage = null;
        if (!StringUtils.isEmpty(reqRespFlagStr)) {
            requestResponseFlagIdForMessage = Integer.parseInt(reqRespFlagStr);
        } else {//如果请求响应标志位空，则从控制码中获取请求响应状态
            String controlCodeStr = HzhrTypeUtil.object2string(messageHead.get(MessageFieldKeyEnum.CONTROL_CODE));
            if (!StringUtils.isEmpty(controlCodeStr)) {
                String controlCodeBin = StrUtil.decimal2binary(Integer.parseInt(controlCodeStr));
                String starteFlag = controlCodeBin.charAt(0) + ""; //通信发启标识：0 服务器端发启 1 设备端发启
                String transFlag = controlCodeBin.charAt(1) + ""; //传输方向标识：0 下行 1 上行

                if (starteFlag.equals(transFlag)) {
                    requestResponseFlagIdForMessage = RequestResponseFlagEnum.REQ.getIdForMessage();
                } else {
                    requestResponseFlagIdForMessage = RequestResponseFlagEnum.RESP.getIdForMessage();
                }
            }
        }

        MessagefieldEntity startcodeField = MessagefieldEntityConstant.MAP.get(messagetmp.getStartcodefieldId());//起始码字段对象
        MessagefieldEntity endcodeField = MessagefieldEntityConstant.MAP.get(messagetmp.getEndcodefieldId());//结束码字段对象
        MessagefieldEntity encyptedbyteField = MessagefieldEntityConstant.MAP.get(messagetmp.getEncryptedbytefieldId());//加密字节字段对象
        MessagefieldEntity crcField = MessagefieldEntityConstant.MAP.get(messagetmp.getCrcfieldId());//校验码字段对象
        MessageheadtmpEntity messageheadtmp = MessageheadtmpEntityConstant.MAP.get(messagetmp.getMessageheadtempId());//报文头模板

        FunctionEntity functionEntity = FunctionEntityConstant.getFunctionEntityByProtocolIdAndFunctionCode(protocolId, functionCode);
        FunctiontmpEntity functiontmp = FunctiontmpEntityConstant.MAP.get(functionEntity.getFunctiontmpId());
        FunctionEntity function = FunctionEntityConstant.getFunctionEntityByProtocolIdAndFunctiontmpId(messagetmp.getProtocolId(), functiontmp.getId());//功能
        DataareatmpEntity dataareatmp = DataareatmpEntityConstant.MAP.get(function.getDataareatmpId());//数据域模板

        int messageSize = 0;
        messageSize += messagetmp.getFieldsizesum();
        messageSize += messageheadtmp.getFieldsizesum();
        if (RequestResponseFlagEnum.REQ.getIdForMessage() == requestResponseFlagIdForMessage) {
            messageSize += dataareatmp.getReqfieldsizesum();
        } else if (RequestResponseFlagEnum.RESP.getIdForMessage() == requestResponseFlagIdForMessage) {
            messageSize += dataareatmp.getRespfieldsizesum();
        }
        int dataAreaSize = 0;
        if (RequestResponseFlagEnum.REQ.getIdForMessage() == requestResponseFlagIdForMessage) {
            dataAreaSize += dataareatmp.getReqfieldsizesum();
        } else if (RequestResponseFlagEnum.RESP.getIdForMessage() == requestResponseFlagIdForMessage) {
            dataAreaSize += dataareatmp.getRespfieldsizesum();
        }

        Map<MessageFieldKeyEnum, Object> messageObj = new HashMap<>();
        messageObj.putAll(messageHead);//写入报文头
        messageObj.putAll(dataArea);//写入报文体
        if (startcodeField != null && startcodeField.getFixedvalue() != null) {
            messageObj.put(MessageFieldKeyEnum.START_CODE, StrUtil.hexStr2decStr(startcodeField.getFixedvalue()));//固定值
        }
        messageObj.put(MessageFieldKeyEnum.MESSAGE_SIZE, messageSize + "");
        messageObj.put(MessageFieldKeyEnum.DATA_AREA_SIZE, dataAreaSize);
        if (encyptedbyteField != null) {
            messageObj.put(MessageFieldKeyEnum.ENCRYPTED_BYTE, StrUtil.FillZeroForLeft("", encyptedbyteField.getSize() * 2));//占位
        }
        if (crcField != null) {
            messageObj.put(MessageFieldKeyEnum.CRC, StrUtil.FillZeroForLeft("", crcField.getSize() * 2));//占位
        }
        if (endcodeField != null) {
            messageObj.put(MessageFieldKeyEnum.END_CODE, StrUtil.hexStr2decStr(endcodeField.getFixedvalue()));//固定值
        }

        return messageObj;
    }
    public Map<MessageFieldKeyEnum, Object> generateMessageObj(int protocolId, int functionTmpId,
                                                                TransferDirEnum transferDir, RequestResponseFlagEnum requestResponseFlag, String iotDeviceDeviceId, String messageId,
                                                                Map<MessageFieldKeyEnum, Object> dataArea) {
        MessagetmpEntity messagetmp = MessagetmpEntityConstant.getMessagetmpEntityByProtocolId(protocolId);
        FunctiontmpEntity functiontmp = FunctiontmpEntityConstant.MAP.get(functionTmpId);

        Map<MessageFieldKeyEnum, Object> messageObj = new HashMap<>();

        MessagefieldEntity startcodeField = MessagefieldEntityConstant.MAP.get(messagetmp.getStartcodefieldId());//起始码字段对象
        MessagefieldEntity endcodeField = MessagefieldEntityConstant.MAP.get(messagetmp.getEndcodefieldId());//结束码字段对象
        MessagefieldEntity encyptedbyteField = MessagefieldEntityConstant.MAP.get(messagetmp.getEncryptedbytefieldId());//加密字节字段对象
        MessagefieldEntity crcField = MessagefieldEntityConstant.MAP.get(messagetmp.getCrcfieldId());//校验码字段对象
        messagetmp.getEndcodefieldId();
        MessageheadtmpEntity messageheadtmp = MessageheadtmpEntityConstant.MAP.get(messagetmp.getMessageheadtempId());//报文头模板
        FunctionEntity function = FunctionEntityConstant.getFunctionEntityByProtocolIdAndFunctiontmpId(messagetmp.getProtocolId(), functiontmp.getId());//功能
        if (function == null) return null;
        String functionCode = function.getCode();//功能码
        DataareatmpEntity dataareatmp = DataareatmpEntityConstant.MAP.get(function.getDataareatmpId());//数据域模板

        int messageSize = 0;
        messageSize += messagetmp.getFieldsizesum();
        messageSize += messageheadtmp.getFieldsizesum();
        if (RequestResponseFlagEnum.REQ.equals(requestResponseFlag)) {
            messageSize += dataareatmp.getReqfieldsizesum();
        } else if (RequestResponseFlagEnum.RESP.equals(requestResponseFlag)) {
            messageSize += dataareatmp.getRespfieldsizesum();
        }
        int dataAreaSize = 0;
        if (RequestResponseFlagEnum.REQ.equals(requestResponseFlag)) {
            dataAreaSize += dataareatmp.getReqfieldsizesum();
        } else if (RequestResponseFlagEnum.RESP.equals(requestResponseFlag)) {
            dataAreaSize += dataareatmp.getRespfieldsizesum();
        }

        if (startcodeField != null && startcodeField.getFixedvalue() != null) {
            messageObj.put(MessageFieldKeyEnum.START_CODE, StrUtil.hexStr2decStr(startcodeField.getFixedvalue()));//固定值
        }
        messageObj.put(MessageFieldKeyEnum.MESSAGE_SIZE, messageSize + "");
        messageObj.put(MessageFieldKeyEnum.FUNCTION_CODE, functionCode);
        if (transferDir != null) {
            messageObj.put(MessageFieldKeyEnum.TRANSFER_DIR, transferDir.getIdForMessage());
        }
        if (requestResponseFlag != null) {
            messageObj.put(MessageFieldKeyEnum.REQ_RESP_FLAG, requestResponseFlag.getIdForMessage());
        }
        messageObj.put(MessageFieldKeyEnum.IOT_DEVICE_ID, iotDeviceDeviceId);
        messageObj.put(MessageFieldKeyEnum.MESSAGE_ID, messageId);
        messageObj.put(MessageFieldKeyEnum.DATA_AREA_SIZE, dataAreaSize);
        messageObj.putAll(dataArea);//写入报文体
        if (encyptedbyteField != null) {
            messageObj.put(MessageFieldKeyEnum.ENCRYPTED_BYTE, StrUtil.FillZeroForLeft("", encyptedbyteField.getSize() * 2));//占位
        }
        if (crcField != null) {
            messageObj.put(MessageFieldKeyEnum.CRC, StrUtil.FillZeroForLeft("", crcField.getSize() * 2));//占位
        }
        if (endcodeField != null) {
            messageObj.put(MessageFieldKeyEnum.END_CODE, StrUtil.hexStr2decStr(endcodeField.getFixedvalue()));//固定值
        }

        return messageObj;
    }

    public String getNextMessageId() {
        String messageId = "";

        messageId += DateUtil.dateToStr(new Date(), "yyMMdd");

        CommandCountEntity commandcount = commandCountService.getCommandcountEntityByDayAndTransdir(new Date());
        Integer count = 0;
        if (commandcount != null) {
            count = commandcount.getCount();
        }
        count += 1;
        messageId += StrUtil.FillZeroForRight(count.toString(), 8);
        return messageId;
    }

    public String getNextMessageId(int protocolId, String deviceId) {
        if (protocolId == 3) {
            try {
                Integer messageId = device_iotDevice_currentMessageIdServiceHelper.getByIotDeviceId(deviceId).getCurrentMessageId();
                return (messageId % 255) + 1 + "";
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        } else {
            String messageId = "";

            messageId += DateUtil.dateToStr(new Date(), "yyMMdd");

            CommandCountEntity commandcount = commandCountService.getCommandcountEntityByDayAndTransdir(new Date());
            Integer count = 0;
            if (commandcount != null) {
                count = commandcount.getCount();
            }
            count += 1;
            messageId += StrUtil.FillZeroForRight(count.toString(), 8);
            return messageId;
        }
    }
}
